<template>
	<view
		class="tab-nav"
		:style="{
			top: `${statusBarHeight + navbarHeight}px`,
		}"
	>
		<!-- 可滚动模式 -->
		<scroll-view
			v-if="scrollable"
			class="tab-list"
			scroll-x
			:show-scrollbar="false"
			enhanced
			:scroll-into-view="scrollIntoId"
		>
			<view class="tab-list-inner" :class="[tabs.length <= 4 ? 'justify-around' : 'justify-start']">
				<view
					v-for="(item, index) in tabs"
					:key="index"
					:id="`tab-${index}`"
					class="tab-item"
					:class="{ active: currentIndex === index }"
					@click="handleTabClick(index)"
				>
					{{ item.name }}
					<view class="active-line" v-if="currentIndex === index" />
				</view>
			</view>
		</scroll-view>

		<!-- 不可滚动模式 -->
		<view v-else class="tab-list no-scroll">
			<view
				class="tab-item"
				v-for="(item, index) in tabs"
				:key="index"
				:class="{ active: currentIndex === index }"
				@click="handleTabClick(index)"
			>
				{{ item.name }}
				<view class="active-line" v-if="currentIndex === index" />
			</view>
		</view>
	</view>
</template>

<script setup lang="ts">
import { ref, computed } from "vue"
import { onPageScroll } from "@dcloudio/uni-app"
import { throttle } from "lodash"
import useCommonStore from "@/store/common"
import { useIsReached } from "@/pages/hy/scenic/hooks/useIsReached"

interface Tab {
	id: string
	name: string
}

interface Props {
	tabs: Array<Tab>
	offsetTop?: number
	scrollable?: boolean
}

const props = withDefaults(defineProps<Props>(), {
	offsetTop: 0,
	scrollable: true, // 默认开启滚动
})

const { isReached } = useIsReached(160)
const { statusBarHeight, navbarHeight } = useCommonStore()
const currentIndex = ref(0)

const scrollIntoId = computed(() => `tab-${currentIndex.value}`)

// 获取元素位置信息
const getElRect = (selector: string): Promise<UniApp.NodeInfo> => {
	return new Promise((resolve) => {
		uni.createSelectorQuery()
			.select(`.${selector}`)
			.boundingClientRect((rect) => {
				resolve(rect as UniApp.NodeInfo)
			})
			.exec()
	})
}

interface RectInfo extends UniApp.NodeInfo {
	distance: number
}
const currentScrollTop = ref(0)
const isScrolling = ref(false)
const scrollTimer = ref<NodeJS.Timeout | null>(null)

onPageScroll((e) => {
	currentScrollTop.value = e.scrollTop
	if (!isScrolling.value) {
		throttledCheck(e.scrollTop)
	}
})

const scrollToElement = async (id: string) => {
	if (scrollTimer.value) {
		clearTimeout(scrollTimer.value)
		scrollTimer.value = null
	}
	const rect = await getElRect(id)
	if (!rect) return

	isScrolling.value = true

	// 计算目标滚动位置
	const targetScrollTop = Math.max(0, rect.top + currentScrollTop.value - props.offsetTop)

	uni.pageScrollTo({
		scrollTop: targetScrollTop,
		duration: 300,
		complete: () => {
			scrollTimer.value = setTimeout(() => {
				isScrolling.value = false
				scrollTimer.value = null
			}, 100)
		},
	})
}

const throttledCheck = throttle((scrollTop: number) => {
	if (!isScrolling.value) {
		checkScroll(scrollTop)
	}
}, 50)
onBeforeUnmount(() => {
	if (scrollTimer.value) {
		clearTimeout(scrollTimer.value)
	}
})
interface ClosestRect {
	index: number
	distance: number
}
const checkScroll = async (scrollTop: number) => {
	if (isScrolling.value) return
	const rectList = await Promise.all(
		props.tabs.map(async (tab) => {
			const rect = await getElRect(tab.id)
			if (!rect) return null
			return {
				...rect,
				distance: Math.abs(rect.top - props.offsetTop),
			} as RectInfo
		})
	)
	const closestIndex = rectList.reduce<ClosestRect>(
		(closest, rect, index) => {
			if (!rect) return closest
			if (closest.index === -1) return { index, distance: rect.distance }
			if (rect.distance < closest.distance) {
				return { index, distance: rect.distance }
			}
			return closest
		},
		{ index: -1, distance: Infinity }
	).index

	// 只在非滚动状态下更新索引
	if (closestIndex !== -1 && closestIndex !== currentIndex.value && !isScrolling.value) {
		currentIndex.value = closestIndex
	}
}

const handleTabClick = (index: number) => {
	if (isScrolling.value || index === currentIndex.value) {
		return
	}
	currentIndex.value = index
	scrollToElement(props.tabs[index].id)
}

onPageScroll((e) => {
	throttledCheck(e.scrollTop)
})
</script>

<style lang="scss" scoped>
.tab-nav {
	position: fixed;
	left: 0;
	right: 0;
	z-index: 20;
	height: 88rpx;
	background-color: #fff;
	border-bottom: 1rpx solid #f5f5f5;
}

// 可滚动模式样式
.tab-list {
	width: 100%;
	height: 88rpx;
	white-space: nowrap;

	&::-webkit-scrollbar {
		display: none;
		width: 0;
		height: 0;
		color: transparent;
	}

	.tab-list-inner {
		display: inline-flex;
		min-width: 100%;
		height: 100%;

		&.justify-around {
			justify-content: space-around;
			padding: 0;

			.tab-item {
				flex: 1;
				padding: 0;
				margin: 0;

				&:not(:last-child) {
					margin-right: 0;
				}
			}
		}

		&.justify-start {
			justify-content: flex-start;
			padding: 0 32rpx;

			.tab-item {
				flex: none;
				padding: 0 32rpx;

				&:not(:last-child) {
					margin-right: 12rpx;
				}
			}
		}
	}
}

// 不可滚动模式样式
.no-scroll {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	height: 88rpx;
	padding: 0 32rpx;

	.tab-item {
		flex: 1;
		text-align: center;
		color: rgba(0, 0, 0, 0.6);
		&.active {
			color: rgba(0, 0, 0, 0.9);
		}
	}
}

// 通用的 tab-item 样式
.tab-item {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 100%;
	font-size: 28rpx;
	color: #333;
	white-space: nowrap;

	&.active {
		font-weight: 500;

		.active-line {
			opacity: 1;
			transform: translateX(-50%) scaleX(1);
		}
	}
}

.active-line {
	position: absolute;
	left: 50%;
	bottom: 0;
	width: 44rpx;
	height: 6rpx;
	background-color: #f8b709;
	border-radius: 6rpx;
	transform: translateX(-50%) scaleX(0);
	opacity: 0;
	transition: all 0.3s ease;
}
</style>
